package com.cc.blog.admin.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.cc.blog.admin.convert.CommentConvert;
import com.cc.blog.admin.domain.dto.DeleteCommentReqDTO;
import com.cc.blog.admin.domain.dto.ExamineCommentReqDTO;
import com.cc.blog.admin.domain.dto.FindCommentPageListReqDTO;
import com.cc.blog.admin.domain.vo.FindCommentPageListRspVO;
import com.cc.blog.admin.event.UpdateCommentEvent;
import com.cc.blog.admin.mapper.CommentMapper;
import com.cc.blog.admin.model.CommentDO;
import com.cc.blog.admin.service.AdminCommentService;
import com.cc.blog.common.enums.CodeEnum;
import com.cc.blog.common.enums.CommentStatusEnum;
import com.cc.blog.common.exception.BusinessException;
import com.cc.blog.common.utils.PageResult;
import com.cc.blog.common.utils.Result;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author cc
 */
@Service
@Slf4j
@AllArgsConstructor
public class AdminCommentServiceImpl implements AdminCommentService {

    private final CommentMapper commentMapper;
    private final ApplicationEventPublisher eventPublisher;

    @Override
    public Result findCommentPageList(FindCommentPageListReqDTO findCommentPageListReqDTO) {
        // 获取当前页、以及每页需要展示的数据数量
        Long current = findCommentPageListReqDTO.getCurrent();
        Long size = findCommentPageListReqDTO.getSize();
        LocalDate startDate = findCommentPageListReqDTO.getStartDate();
        LocalDate endDate = findCommentPageListReqDTO.getEndDate();
        String routerUrl = findCommentPageListReqDTO.getRouterUrl();
        Integer status = findCommentPageListReqDTO.getStatus();
        // 执行分页查询
        Page<CommentDO> commentDOPage = commentMapper.selectPageList(current, size, routerUrl, startDate, endDate, status);
        List<CommentDO> commentDOS = commentDOPage.getRecords();
        // DO 转 VO
        List<FindCommentPageListRspVO> vos = null;
        if (!CollectionUtils.isEmpty(commentDOS)) {
            vos = commentDOS.stream()
                    .map(commentDO -> CommentConvert.INSTANCE.convertDO2VO(commentDO))
                    .collect(Collectors.toList());
        }
        return PageResult.success(commentDOPage, vos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result deleteComment(DeleteCommentReqDTO deleteCommentReqDTO) {
        Long commentId = deleteCommentReqDTO.getId();
        // 查询该评论是一级评论，还是二级评论
        CommentDO commentDO = commentMapper.selectById(commentId);
        // 判断评论是否存在
        if (Objects.isNull(commentDO)) {
            log.warn("该评论不存在, commentId: {}", commentId);
            throw new BusinessException(CodeEnum.COMMENT_NOT_FOUND);
        }
        // 删除评论
        commentMapper.deleteById(commentId);
        Long replayCommentId = commentDO.getReplyCommentId();
        // 一级评论
        if (Objects.isNull(replayCommentId)) {
            // 删除子评论
            commentMapper.deleteByParentCommentId(commentId);
        } else { // 二级评论
            // 删除此评论, 以及此评论下的所有回复
            this.deleteAllChildComment(commentId);
        }
        return Result.success();
    }

    @Override
    public Result examine(ExamineCommentReqDTO examineCommentReqDTO) {
        Long commentId = examineCommentReqDTO.getId();
        Integer status = examineCommentReqDTO.getStatus();
        String reason = examineCommentReqDTO.getReason();
        // 根据提交的评论 ID 查询该条评论
        CommentDO commentDO = commentMapper.selectById(commentId);
        // 判空
        if (Objects.isNull(commentDO)) {
            log.warn("该评论不存在, commentId: {}", commentId);
            throw new BusinessException(CodeEnum.COMMENT_NOT_FOUND);
        }
        // 评论当前状态
        Integer currStatus = commentDO.getStatus();
        // 若未处于待审核状态
        if (!Objects.equals(currStatus, CommentStatusEnum.WAIT_EXAMINE.getCode())) {
            log.warn("该评论未处于待审核状态, commentId: {}", commentId);
            throw new BusinessException(CodeEnum.COMMENT_STATUS_NOT_WAIT_EXAMINE);
        }
        // 更新评论
        commentMapper.updateById(CommentDO.builder()
                .id(commentId)
                .status(status)
                .reason(reason)
                .updateTime(LocalDateTime.now())
                .build());
        // 发送文章发布事件
        eventPublisher.publishEvent(new UpdateCommentEvent(this, commentId));
        return Result.success();
    }

    /**
     * 递归删除所有子评论
     * @param commentId
     */
    private void deleteAllChildComment(Long commentId) {
        // 查询此评论的所有回复
        List<CommentDO> childCommentDOS = commentMapper.selectByReplyCommentId(commentId);
        if (CollectionUtils.isEmpty(childCommentDOS)) {
            return;
        }
        // 循环递归删除
        childCommentDOS.forEach(childCommentDO -> {
            Long childCommentId = childCommentDO.getId();
            commentMapper.deleteById(childCommentId);
            // 递归调用
            deleteAllChildComment(childCommentId);
        });
    }

}